
import neko.zip.Compress;
import neko.io.File;
import neko.io.FileOutput;
import neko.FileSystem;

import swf.Header;
import swf.BinaryData;
import swf.ExportAssets;
import swf.ShowFrame;
import swf.End;

typedef FileItem = { name : String, data : String }

class SwfFS {
	static var _instance : SwfFS;
	public static function main () : Void {
		_instance = new SwfFS();
	}
	
	static var versionID = String.fromCharCode( 0 );
	
	var basePath : String;
	var items : Array<FileItem>;
	
	// options:
	var outfile : String;
	var classname : String;
	var rootdir : String;
	
	private function new () {
		var args = neko.Sys.args();
		
		if( !parseOptions( args ) ) {
			showUsage();
			return;
		}
		
		var path = args.shift();
		if( (path == null) || !FileSystem.exists( path ) ) {
			showUsage();
			return;
		}
		
		basePath = FileSystem.fullPath( path );
		items = new Array<FileItem>();
		
		if( !FileSystem.isDirectory( path ) ) {
			basePath = basePath.substr( 0, basePath.lastIndexOf( "/" ) );
			readFile( FileSystem.fullPath( path ) );
		} else {
			readDirectory( basePath );
		}
		
		var output = File.write( outfile, true );
		var content = "";
		content += new BinaryData( 1, encode() );
		content += new ExportAssets( [{ id: 1, name: classname }] );
		content += new ShowFrame();
		content += new End();

		var hdr = "";
		hdr += new Header( 19 + content.length, 0, 0 );
		output.write( hdr + content );
	}
	
	function parseOptions ( args : Array<String>) : Bool {
		outfile = "swffs.swf";
		classname = "SwfFS";
		rootdir = "";
		
		if( args.length < 2 ) {
			return true;
		}
		
		while( args[ 0 ].substr( 0, 1 ) == "-" ) {
			var option = args.shift();
			if( (option == "-of") || (option == "-outfile") ) {
				outfile = args.shift();
			} else if( (option == "-cn") || (option == "-classname") ) {
				classname = args.shift();
			} else if( (option == "-rd") || (option == "-rootdir") ) {
				rootdir = args.shift() + "/";
			} else {
				return false;
			}
		}
		
		return true;
	}
	
	function readDirectory ( path : String ) : Void {
		for( file in FileSystem.readDirectory( path ) ) {
			var fullPath = path + "/" + file;
			if( FileSystem.isDirectory( fullPath ) ) {
				readDirectory( fullPath );
			} else {
				readFile( fullPath );
			}
		}
	}
	
	function readFile ( fullPath : String ) : Void {
		var name = rootdir + fullPath.substr( basePath.length + 1 );
		items.push( { name: name, data: File.getContent( fullPath ) } );
		neko.Lib.println( name );
		
	}
	
	function encode () : String {
		var header = "SwfFS" + versionID;
		var table = "";
		var content = "";
		for( item in items ) {
			var name = String.fromCharCode( item.name.length ) + item.name;
			table += name + intToString( content.length ) + intToString( item.data.length );
			content += item.data;
		}
		return header + intToString(table.length) + table + content;
	}
	
	function intToString ( n : Int ) : String {
		var str = new StringBuf();
		str.addChar( (n >>> 24) & 0xff );
		str.addChar( (n >>> 16) & 0xff );
		str.addChar( (n >>> 8) & 0xff );
		str.addChar( n & 0xff );
		
		return str.toString();
	}
	
	function showUsage () : Void {
		var usage = "SwfFS version 0.1\n\n";
		usage += "usage: swffs [options] <directory>\n\n";
		usage += "possible options are:\n\n";
		usage += " -outfile or -of <name>\n";
		usage += "   How to name the SWF. Default is 'swffs.swf'.\n\n";
		usage += " -classname or -cn <name>\n";
		usage += "   How to name the class. Default is 'SwfFS'.\n\n";
		usage += " -rootdir or -rd <name>\n";
		usage += "   Base path to prefix file names with. Empty by default.\n\n";
		
		usage += "http://snafoo.org/SwfFS/\n";
		
		neko.Lib.print( usage );
	}
}
